using UnityEngine;
using System.Collections;

public abstract class Menu : MonoBehaviour 
{
	public Renderer[] menuElements;
	
	private string sceneName;

	protected bool ready;
	protected float amount;
	protected MenuManager _manager;
	protected float standTime;
	
	public float yieldReturnControls;
	
	public int limit;
	
	#region Variaveis_NavigationX
	
	protected int actualNavigationPosX;
	protected int lastNumberX;
	private int limitX;
	protected bool readyX = true;
	
	#endregion
	
	#region Variaveis_NavigationY
	
	protected int lastNumberY;
	protected int actualNavigationPosY;
	private int limitY;
	protected bool readyY = true;

	#endregion
	
	#region Variaveis_NavigationY
	
	private Renderer[,] matrixRenderer;
	private int offsetLine = 0;
	private int saveY = 0;

	#endregion
	
	private float yieldTime;
	
	private bool hasCoroutine;
	
	protected int actualRenderer;
	protected int lastRenderer;
	
	private int currentActual;
	private bool currentReady = true;
	
	private Renderer button;
	protected bool back;
	
	protected bool hasPressEnter()
	{
		if(Input.GetButtonDown("Jump") || (Input.GetKeyDown(KeyCode.KeypadEnter) ||  Input.GetKeyDown(KeyCode.Return)))
			return true;
			
		return false;	
	}
	
	protected void beginNavigationX(int limit,float standTime)
	{
		limitX = limit;
		yieldTime = standTime;
	}
	
	protected void beginNavigationY(int limit,float standTime)
	{
		limitY = limit;
		yieldTime = standTime;
		actualNavigationPosY = 0;
		lastNumberY = actualNavigationPosY;
	}
	
	protected void navigationX()
	{
		if(readyX)
		{
			if(Input.GetAxisRaw("Horizontal") == -1 && actualNavigationPosX > 0)
			{
				lastNumberX = actualNavigationPosX;
				actualNavigationPosX --;
				StartCoroutine(canNavigateX());
			}
			
			if(Input.GetAxisRaw("Horizontal") == 1 && actualNavigationPosX < limitX)
			{
				lastNumberX = actualNavigationPosX;
				actualNavigationPosX ++;
				StartCoroutine(canNavigateX());
			}
			
		}
		
	}
	
	protected void navigationY()
	{

		if(readyY)
		{
			if(Input.GetAxisRaw("Vertical") == 1 && actualNavigationPosY > 0)
			{
				lastNumberY = actualNavigationPosY;
				actualNavigationPosY --;
				StartCoroutine(canNavigateY());
			}
			
			if(Input.GetAxisRaw("Vertical") == -1 && actualNavigationPosY < limitY)
			{
				lastNumberY = actualNavigationPosY;
				actualNavigationPosY ++;			
				StartCoroutine(canNavigateY());
			}
			
		}
		
	}
	
	private IEnumerator canNavigateX()
	{			
		readyX = false;
		yield return new WaitForSeconds(yieldTime);
		readyX = true;
	}
	
	private IEnumerator canNavigateY()
	{
		readyY = false;
		yield return new WaitForSeconds(yieldTime);
		readyY = true;
	}
	
	private IEnumerator canNavigateMatrix()
	{
		
		readyX = false;
		readyY = false;
		
		yield return new WaitForSeconds(yieldTime);
		readyY = true;
		
		if(actualNavigationPosY < limitY+1)
		{
			readyX = true;		
		}
	}
	
	protected void changeLimitX(int number)
	{
		limitX = number;
	}
	
	protected void changeLimitY(int number)
	{
		limitY = number;
	}
	
	public void beginMatrixNavigation(int newXLimit,int newYLimit,int offsetLine,Renderer backButton)
	{
		this.button = backButton;
		this.limitX = newXLimit;
		this.limitY = newYLimit;
		this.offsetLine = offsetLine;
		yieldTime = yieldReturnControls;
		
		matrixRenderer = new Renderer[limitX+1,limitY+1];
		
		int saveIndex = 0;
		
		for (int i = 0; i <= limitY; i++) 
		{
			for (int b = 0; b <= limitX; b++) 
			{
				matrixRenderer[b,i] = menuElements[saveIndex];
								saveIndex ++;

			}	
		}
		
		int currentValue = PlayerPrefs.GetInt("CurrentScene")-1;
		
		int line = 0;
		
		while(currentValue > offsetLine)
		{
			currentValue -= offsetLine;
			line ++;
		}
		
		int column = currentValue;
		
		actualNavigationPosX = column-1;
		actualNavigationPosY = line;
		
		actualRenderer = (actualNavigationPosX + ((offsetLine)*actualNavigationPosY));
		lastRenderer = actualRenderer;
		ready = true;
	}
	
	public void MatrixNavigation()
	{
		if(readyX && !back)
		{
			if((Input.GetAxisRaw("Horizontal") == -1 && actualNavigationPosX > 0))
			{
				lastRenderer = actualRenderer;
				
				if(actualNavigationPosX == 0)
				{
					if(actualNavigationPosY > 0)
					{
						if(matrixRenderer[limitX,actualNavigationPosY-1].gameObject.GetComponent<LevelElements>().hasEnabled)
						{
							actualNavigationPosY --;
							actualNavigationPosX = limitX;
						}
					}
				}
				else
				{
					if(matrixRenderer[actualNavigationPosX-1,actualNavigationPosY].gameObject.GetComponent<LevelElements>().hasEnabled)
					actualNavigationPosX --;
				}
				
				actualRenderer = actualNavigationPosX + ((offsetLine)*actualNavigationPosY);
				StopAllCoroutines();
				StartCoroutine(canNavigateMatrix());
			}
			if((Input.GetAxisRaw("Horizontal") == 1 && actualNavigationPosX < limitX))
			{
				lastRenderer = actualRenderer;
				
				if(actualNavigationPosX == limitX)
				{
					if(actualNavigationPosY < limitY)
					{
						if(matrixRenderer[0,actualNavigationPosY+1].gameObject.GetComponent<LevelElements>().hasEnabled)
						{
							actualNavigationPosX = 0;
							actualNavigationPosY ++;
						}
						
					}
				}
				else
				{
					if(matrixRenderer[actualNavigationPosX+1,actualNavigationPosY].gameObject.GetComponent<LevelElements>().hasEnabled)
					{
						actualNavigationPosX ++;
					}
				}
				
				actualRenderer = actualNavigationPosX + ((offsetLine)*actualNavigationPosY);
				StopAllCoroutines();
				StartCoroutine(canNavigateMatrix());
			}	
		}
		
		if(readyY)
		{
			if(Input.GetAxisRaw("Vertical") == 1 && actualNavigationPosY > 0)
			{
				lastRenderer = actualRenderer;
				
				if(actualNavigationPosY > 0)
				{
					if(actualNavigationPosY > limitY)
					{
						if(saveY == 1)
							saveY = 0;
						
						actualNavigationPosY = saveY;
						back = false;
						this.effectSwitchRandomColor(menuElements[actualRenderer]);
						Destroy(button.gameObject.GetComponent<SpecialCube>());
						button.material.color = Color.white;

					}
					
					if(actualNavigationPosY != 0)
					{
						if(matrixRenderer[actualNavigationPosX,actualNavigationPosY-1].gameObject.GetComponent<LevelElements>().hasEnabled)
						{
							actualNavigationPosY --;
						}
					}
					
				}
				
				actualRenderer = actualNavigationPosX + ((offsetLine)*actualNavigationPosY);
				StopAllCoroutines();
				StartCoroutine(canNavigateMatrix());
			}

			
			if(Input.GetAxisRaw("Vertical") == -1  && actualNavigationPosY < limitY)
			{
				lastRenderer = actualRenderer;
				
				if(actualNavigationPosY < limitY)
				{
					if(matrixRenderer[actualNavigationPosX,actualNavigationPosY+1].gameObject.GetComponent<LevelElements>().hasEnabled)
					{
						actualNavigationPosY ++;
					}
					else
					{
						saveY = actualNavigationPosY;
						actualNavigationPosY = limitY+1;
						back = true;
						if(!button.gameObject.GetComponent<SpecialCube>())
						button.gameObject.AddComponent("SpecialCube");
						Destroy(menuElements[actualRenderer].gameObject.GetComponent<SpecialCube>());
						menuElements[actualRenderer].material.color = Color.white;
					}
				}
		
				if(!back)
				{
					actualRenderer = actualNavigationPosX + ((offsetLine)*actualNavigationPosY);
				}
				
				
				StopAllCoroutines();
				StartCoroutine(canNavigateMatrix());
			}
			else if(Input.GetAxisRaw("Vertical") == -1  && actualNavigationPosY >= limitY)
			{
				saveY = actualNavigationPosY;
				actualNavigationPosY = limitY+1;
				back = true;
				if(!button.gameObject.GetComponent<SpecialCube>())
				button.gameObject.AddComponent("SpecialCube");
				Destroy(menuElements[actualRenderer].gameObject.GetComponent<SpecialCube>());
				menuElements[actualRenderer].material.color = Color.white;
			}

			
		}
	}
	
	protected void CanMoveX()
	{
		if(!readyX)
			if(Input.GetAxisRaw("Horizontal") == 0)
				readyX = true;
	}

	protected void CanMoveY()
	{
		if(!readyY)
			if(Input.GetAxisRaw("Vertical") == 0)
				readyY = true;
	}
	
	protected void effectSwitchRandomColor(int actual,int last)
	{		
		if(!currentReady)
			if(actual != currentActual)
				currentReady = true;
		
		this.menuElements[last].material.color = Color.white;
		
		if(currentReady)
		{
			Color randomColor = new Color(Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),this.menuElements[actual].material.color.a);
			
			while(randomColor.Equals(Color.white))
			{
				randomColor = new Color(Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),this.menuElements[actual].material.color.a);
			}
			
			this.menuElements[actual].material.color = randomColor;

		}
		
		currentActual = actual;
		currentReady = false;
	}

	protected void effectSwitchRandomColor(Renderer obj)
	{

			Color randomColor = new Color(Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),Random.Range(0.0f,1.0f),1);
			
			if(randomColor.Equals(Color.white))
			{
				randomColor = new Color(Random.Range(0.5f,1.0f),Random.Range(0.5f,1.0f),Random.Range(0.5f,1.0f),1);
			}
			
			obj.material.color = randomColor;

	}
	
	protected void effectSwitchFlashColors(int actual,int last)
	{
		if(this.menuElements[last].gameObject.GetComponent<SpecialCube>())
			Destroy(this.menuElements[last].gameObject.GetComponent<SpecialCube>());
				
		this.menuElements[last].material.color = Color.white;
		
		if(!this.menuElements[actual].gameObject.GetComponent<SpecialCube>())
			this.menuElements[actual].gameObject.AddComponent("SpecialCube");
	}
	
	protected void effectSwitchFlashColors(int actual,int last,Color colorDeactive)
	{
		if(this.menuElements[last].gameObject.GetComponent<SpecialCube>())
			Destroy(this.menuElements[last].gameObject.GetComponent<SpecialCube>());
				
		this.menuElements[last].material.color = colorDeactive;
		
		if(!this.menuElements[actual].gameObject.GetComponent<SpecialCube>())
			this.menuElements[actual].gameObject.AddComponent("SpecialCube");
	}

	protected void effectSwitchBlackAndWhite(int actual,int last)
	{
		if(this.menuElements[last].gameObject.GetComponent<SpecialCubeBlackAndWhite>())
			Destroy(this.menuElements[last].gameObject.GetComponent<SpecialCubeBlackAndWhite>());
				
		this.menuElements[last].material.color = Color.white;
		
		if(!this.menuElements[actual].gameObject.GetComponent<SpecialCubeBlackAndWhite>())
			this.menuElements[actual].gameObject.AddComponent("SpecialCubeBlackAndWhite");

	}
	
	public abstract void effectSwitch(int number);
	
	public abstract void executeAction(int number);
}


public enum MenuType
{
	NAVIGATEX,
	NAVIGATEY,
	NAVIGATEXY
}